import 'dart:convert';
import 'dart:io' as io;

import 'package:dio/dio.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:series_play/comm/comm_constant.dart';
import 'package:series_play/comm/ext/string_ext.dart';
import 'package:series_play/net/header_interceptor.dart';
import 'package:series_play/net/http_exception.dart';
import 'package:series_play/net/http_response.dart';
import 'package:series_play/utils/log.dart';

/// Http请求管理类
class HttpManager {
  final Dio _dio = Dio();

  Dio get dio => _dio;

  static final HttpManager _instance = HttpManager._();

  static HttpManager get instance => _instance;

  /// 私有化
  HttpManager._() {
    _configDio();
  }

  _configDio() {
    _dio.options
      ..receiveTimeout = 60.seconds
      ..connectTimeout = 60.seconds
      ..baseUrl = CommConstant.baseUrl
      ..contentType = 'application/json;Charset=UTF08'
      ..headers = {
        'Content-Type': 'application/json; charset=UTF-8',
        'Accept': 'application/json',
      }
      ..responseType = ResponseType.json;
    _dio.interceptors.add(HeaderInterceptor());
    // 日志输出
    _dio.interceptors.add(
      LogInterceptor(requestBody: true, responseBody: true),
    );
  }

  /// get 请求
  Future<HttpResponse<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(Map<String, dynamic>)? fromJson,
    T Function(List<dynamic>)? fromJsonList,
  }) async {
    final result = await _safeRequest(
      () => _dio.get(
        path,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      ),
      fromJson: fromJson,
      fromJsonList: fromJsonList,
    );
    // Log.api(path, result.code, result.data , method: 'get');
    return result;
  }

  /// Post 请求
  Future<HttpResponse<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(Map<String, dynamic>)? fromJson,
    T Function(List<dynamic>)? fromJsonList,
  }) async {
    final result = await _safeRequest(
      () => _dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      ),
      fromJson: fromJson,
      fromJsonList: fromJsonList,
    );
    // Log.api(path, result.code, result.data , method: 'post');
    return result;
  }

  /// delete
  Future<HttpResponse<T>> delete<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
    T Function(Map<String, dynamic>)? fromJson,
    T Function(List<dynamic>)? fromJsonList,
  }) async {
    final result = await _safeRequest<T>(
      () => _dio.delete(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options,
        cancelToken: cancelToken,
      ),
      fromJson: fromJson,
      fromJsonList: fromJsonList,
    );
    // Log.api(path, result.code, result.data , method: 'delete');
    return result;
  }

  Future<HttpResponse<T>> _safeRequest<T>(
    Function request, {
    T Function(Map<String, dynamic>)? fromJson,
    T Function(List<dynamic>)? fromJsonList,
  }) async {
    try {
      final res = await request.call();
      return _handleResponse<T>(
        res,
        fromJson: fromJson,
        fromJsonList: fromJsonList,
      );
    } on DioException catch (e) {
      Log.e('DioException');
      return _handleError<T>(e);
    } on io.HttpException catch (e) {
      // 基本是连接异常 404/502等
      Log.e('io.HttpException');
      return HttpResponse(code: -1, message: e.message);
    } on HttpException catch (e) {
      Log.e('HttpException');
      e.toString().showToast();
      // 业务异常 或者链接异常 通知controller 更新ui层
      return HttpResponse(code: e.code, message: e.message);
    } on Exception catch (e) {
      Log.e(e);
      Log.e('未知异常', e.toString());
      return HttpResponse(code: -1, message: '未知');
    }
  }

  /// 处理响应
  HttpResponse<T> _handleResponse<T>(
    Response response, {
    T Function(Map<String, dynamic>)? fromJson,
    T Function(List<dynamic>)? fromJsonList,
  }) {
    if (response.data is String) {
      response.data = json.decode(response.data);
    }

    HttpResponse<T> httpResponse = HttpResponse<T>.fromJson(
      response.data,
      fromJson: fromJson,
      fromJsonList: fromJsonList,
    );

    if (!httpResponse.isSuccess) {
      // 这里根据业务处理 暂时这样
      throw HttpException(httpResponse.code, httpResponse.message);
    }

    return httpResponse;
  }

  /// 错误
  ///
  /// todo 业务异常状态吗处理 错误状态 是否要Toast(提示要国际化)
  Future<HttpResponse<T>> _handleError<T>(DioException e) async {
    Log.e('Request error: ${e.type} - ${e.message}');

    switch (e.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.sendTimeout:
      case DioExceptionType.receiveTimeout:
        throw HttpException(-1, '网络连接超时');
      case DioExceptionType.badResponse:
        if (e.response != null) {
          try {
            HttpResponse<T> errorResponse = HttpResponse<T>.fromJson(
              e.response!.data,
            );
            throw HttpException(errorResponse.code, errorResponse.message);
          } catch (_) {
            throw HttpException(e.response?.statusCode ?? -1, '服务器异常');
          }
        } else {
          throw HttpException(-1, '服务器异常');
        }
      case DioExceptionType.cancel:
        throw HttpException(-1, '请求取消');
      case DioExceptionType.unknown:
      default:
        throw HttpException(-1, '网络连接失败');
    }
  }
}
